#ifndef AGGREGATEFUNCTIONRESULT_H_JM_20130222
#define AGGREGATEFUNCTIONRESULT_H_JM_20130222

#include "../BufferedOutputBox.h"
#include "../../LogConf.h"

namespace jm4bbx {

	class  AggregateFunctionResult 
		: public BufferedOneOutputBox<IntegerKeyRecord> {
		JM_USE_LOGGER(boxes_aggregateFunctions_AggregatedFunctionResult_logger)
	public:
		static const  int INPUT_START = 1;
		static const  groupType OUTPUT_GROUP;	
		static const  columnType OUTPUT_COLUMN;
		static const  outType OUT_ARC;
		static const char* INPUT_COUNT_PARAM_NAME;

		virtual void initAggregatedValue() = 0;
		virtual void aggregateValue(int vlaue, int aggIndex) = 0;
		virtual void outputAggregatedValue() = 0;

		AggregateFunctionResult(const BoxParamPack& p) 
			: BufferedOneOutputBox(p, OUTPUT_GROUP, OUTPUT_COLUMN, OUT_ARC) {
				inputCount_ = getBoxParameterValue(p, INPUT_COUNT_PARAM_NAME, 1);
		}

		virtual void initImpl() {
			add_group(OUTPUT_GROUP, OUTPUT_COLUMN, 
				get_output_descriptors(OUT_ARC));

			for (int i = INPUT_START; i < INPUT_START + inputCount_; ++i) {
				add_group(groupType(i), columnType(i), 
					get_input_descriptors(inType(i - INPUT_START)));
			}
			
			initBufferedOutputs();
			wait4Receive();
		}

		virtual void syncMachEtwas() {

			GroupPtr ig = getGroupPtr(groupType(INPUT_START));
			if (!ig->isPoisoned()) {

		

				initAggregatedValue();

				for (int i = INPUT_START; i < INPUT_START + inputCount_; ++i) {	
					ig = getGroupPtr(groupType(i));
					int aggIndex = 0;
					for (;ig->getReadPosition() < ig->getReadEnd(); ig->moveReadPosition()) {
						auto value = get_data<int>(columnType(i))[ig->getReadPosition()];
						LOG_D("aggregate result value: " << value)
						aggregateValue(value, aggIndex++);				
					}
					
				}

				outputAggregatedValue();
				//addOutputData(IntegerKeyRecord(0, sum));
				// Priechod datami ktore sa maju spracovat. 
				sendOutputData();


				//assert(!(ig->getReadPosition() < ig->getReadEnd()));
				assert(isOutputEmpty());
		
				//send_poisoned(OUT_ARC);
				sendSignalsOut(true);
			}
			wait4Receive();
		}

	private:
		int inputCount_;
		/// Zahajenie cakania na vstup.
		void wait4Receive() {
			for (int i = INPUT_START; i < INPUT_START + inputCount_; ++i) {
				receive(inType(i-INPUT_START), groupType(i));
			}
		}
	};

} // namespace jm4bbx


#endif
